<!DOCTYPE html>
<!-- saved from url=(0046)http://mybatis.org/spring/zh/transactions.html -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh" lang="zh"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="author" content="Hunter Presnall">
    <meta name="author" content="Eduardo Macarron">
    <meta name="author" content="Nan Lei">
    <meta name="Date-Revision-yyyymmdd" content="20200309">
    <meta http-equiv="Content-Language" content="zh">
    <title>mybatis-spring – MyBatis-Spring | 事务</title>
    <link rel="stylesheet" href="./mybatis-spring – MyBatis-Spring _ 事务_files/apache-maven-fluido-1.7.min.css">
    <link rel="stylesheet" href="./mybatis-spring – MyBatis-Spring _ 事务_files/site.css">
    <link rel="stylesheet" href="./mybatis-spring – MyBatis-Spring _ 事务_files/print.css" media="print">
    <script type="text/javascript" src="./mybatis-spring – MyBatis-Spring _ 事务_files/apache-maven-fluido-1.7.min.js.下载"></script>
  </head>
  <body class="topBarDisabled">
    <div class="container-fluid">
      <div id="banner">
        <div class="pull-left"><div id="bannerLeft"><h2>mybatis-spring</h2>
</div>
</div>
        <div class="pull-right"><a href="http://mybatis.org/" id="bannerRight" title="MyBatis logo"><img src="./mybatis-spring – MyBatis-Spring _ 事务_files/mybatis-logo.png" alt="MyBatis logo"></a></div>
        <div class="clear"><hr></div>
      </div>

      <div id="breadcrumbs">
        <ul class="breadcrumb">
        <li id="publishDate">最近更新: 09 三月 2020<span class="divider">|</span>
</li>
          <li id="projectVersion">版本: 2.0.4</li>
        </ul>
      </div>
      <div class="row-fluid">
        <div id="leftColumn" class="span2">
          <div class="well sidebar-nav">
    <ul class="nav nav-list">
      <li class="nav-header">参考文档</li>
    <li><a href="http://mybatis.org/spring/zh/index.html" title="简介"><span class="none"></span>简介</a></li>
    <li><a href="http://mybatis.org/spring/zh/getting-started.html" title="入门"><span class="none"></span>入门</a></li>
    <li><a href="http://mybatis.org/spring/zh/factorybean.html" title="SqlSessionFactoryBean"><span class="none"></span>SqlSessionFactoryBean</a></li>
    <li class="active"><a href="http://mybatis.org/spring/zh/transactions.html#"><span class="icon-chevron-down"></span>事务</a>
    <ul class="nav nav-list">
    <li><a href="http://mybatis.org/spring/zh/transactions.html#configuration" title="标准配置"><span class="none"></span>标准配置</a></li>
    <li><a href="http://mybatis.org/spring/zh/transactions.html#container" title="交由容器管理事务"><span class="none"></span>交由容器管理事务</a></li>
    <li><a href="http://mybatis.org/spring/zh/transactions.html#programmatic" title="编程式事务管理"><span class="none"></span>编程式事务管理</a></li>
    </ul>
</li>
    <li><a href="http://mybatis.org/spring/zh/sqlsession.html" title="使用 SqlSession"><span class="icon-chevron-right"></span>使用 SqlSession</a></li>
    <li><a href="http://mybatis.org/spring/zh/mappers.html" title="注入映射器"><span class="icon-chevron-right"></span>注入映射器</a></li>
    <li><a href="http://mybatis.org/spring/zh/boot.html" title="使用 Spring Boot"><span class="none"></span>使用 Spring Boot</a></li>
    <li><a href="http://mybatis.org/spring/zh/using-api.html" title="使用 MyBatis API"><span class="none"></span>使用 MyBatis API</a></li>
    <li><a href="http://mybatis.org/spring/zh/batch.html" title="使用 Spring Batch"><span class="none"></span>使用 Spring Batch</a></li>
    <li><a href="http://mybatis.org/spring/zh/sample.html" title="示例代码"><span class="none"></span>示例代码</a></li>
      <li class="nav-header">项目文档</li>
    <li><a href="http://mybatis.org/spring/zh/project-info.html" title="项目信息"><span class="icon-chevron-right"></span>项目信息</a></li>
    <li><a href="http://mybatis.org/spring/zh/project-reports.html" title="项目报表"><span class="icon-chevron-right"></span>项目报表</a></li>
</ul>
          <hr>
          <div id="poweredBy">
            <div class="clear"></div>
            <div class="clear"></div>
            <div class="clear"></div>
            <div class="clear"></div>
<a href="http://maven.apache.org/" title="构建依靠 Maven" class="poweredBy"><img class="builtBy" alt="构建依靠 Maven" src="./mybatis-spring – MyBatis-Spring _ 事务_files/maven-feather.png"></a>
            </div>
          </div>
        </div>
        <div id="bodyColumn" class="span10">


  
    <div class="section">
<h2><a name="a.E4.BA.8B.E5.8A.A1"></a>事务</h2>
      
<p>
        一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器，MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。
      </p>
      
<p>
        一旦配置好了 Spring 的事务管理器，你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间，一个单独的 <tt>SqlSession</tt> 对象将会被创建和使用。当事务完成时，这个 session 会以合适的方式提交或回滚。
      </p>
      
<p>
        事务配置好了以后，MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。
      </p>
  
    <a name="configuration"></a>
<div class="section" id="configuration">
<h3><a name="a.E6.A0.87.E5.87.86.E9.85.8D.E7.BD.AE"></a>标准配置</h3>
      
<p>
        要开启 Spring 的事务处理功能，在 Spring 的配置文件中创建一个 <tt>DataSourceTransactionManager</tt> 对象：
      </p>
      
<div class="source"><pre class="prettyprint"><span class="tag">&lt;bean</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"transactionManager"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;constructor-arg</span><span class="pln"> </span><span class="atn">ref</span><span class="pun">=</span><span class="atv">"dataSource"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;/bean&gt;</span></pre></div>

      
<div class="source"><pre class="prettyprint"><span class="lit">@Bean</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="typ">DataSourceTransactionManager</span><span class="pln"> transactionManager</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DataSourceTransactionManager</span><span class="pun">(</span><span class="pln">dataSource</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre></div>

      
<p>
        传入的 <tt>DataSource</tt> 可以是任何能够与 Spring 兼容的 JDBC <tt>DataSource</tt>。包括连接池和通过 JNDI 查找获得的 <tt>DataSource</tt>。
      </p>
      
<p>
        注意：为事务管理器指定的 <tt>DataSource</tt> <b>必须</b>和用来创建 <tt>SqlSessionFactoryBean</tt> 的是同一个数据源，否则事务管理器就无法工作了。
      </p>
    </div>

    <a name="container"></a>
<div class="section" id="container">
<h3><a name="a.E4.BA.A4.E7.94.B1.E5.AE.B9.E5.99.A8.E7.AE.A1.E7.90.86.E4.BA.8B.E5.8A.A1"></a>交由容器管理事务</h3>
      
<p>
        如果你正使用一个 JEE 容器而且想让 Spring 参与到容器管理事务（Container managed transactions，CMT）的过程中，那么 Spring 应该被设置为使用 JtaTransactionManager 或由容器指定的一个子类作为事务管理器。最简单的方式是使用 Spring 的事务命名空间或使用 <tt>JtaTransactionManagerFactoryBean</tt>：
      </p>
      
<div class="source"><pre class="prettyprint"><span class="tag">&lt;tx:jta-transaction-manager</span><span class="pln"> </span><span class="tag">/&gt;</span></pre></div>

      
<div class="source"><pre class="prettyprint"><span class="lit">@Bean</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="typ">JtaTransactionManager</span><span class="pln"> transactionManager</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JtaTransactionManagerFactoryBean</span><span class="pun">().</span><span class="pln">getObject</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre></div>

      
<p>
        在这个配置中，MyBatis 将会和其它由容器管理事务配置的 Spring 事务资源一样。Spring 会自动使用任何一个存在的容器事务管理器，并注入一个 <tt>SqlSession</tt>。如果没有正在进行的事务，而基于事务配置需要一个新的事务的时候，Spring 会开启一个新的由容器管理的事务。
      </p>
      
<p>
        注意，如果你想使用由容器管理的事务，而<b>不想</b>使用 Spring 的事务管理，你就<b>不能</b>配置任何的 Spring 事务管理器。并<b>必须配置</b> <tt>SqlSessionFactoryBean</tt> 以使用基本的 MyBatis 的 <tt>ManagedTransactionFactory</tt>：
      </p>
      
<div class="source"><pre class="prettyprint"><span class="tag">&lt;bean</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"sqlSessionFactory"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"org.mybatis.spring.SqlSessionFactoryBean"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;property</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"dataSource"</span><span class="pln"> </span><span class="atn">ref</span><span class="pun">=</span><span class="atv">"dataSource"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
  </span><span class="tag">&lt;property</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"transactionFactory"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;bean</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"org.apache.ibatis.transaction.managed.ManagedTransactionFactory"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
  </span><span class="tag">&lt;/property&gt;</span><span class="pln">  
</span><span class="tag">&lt;/bean&gt;</span></pre></div>

      
<div class="source"><pre class="prettyprint"><span class="lit">@Bean</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="typ">SqlSessionFactory</span><span class="pln"> sqlSessionFactory</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="typ">SqlSessionFactoryBean</span><span class="pln"> factoryBean </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlSessionFactoryBean</span><span class="pun">();</span><span class="pln">
  factoryBean</span><span class="pun">.</span><span class="pln">setDataSource</span><span class="pun">(</span><span class="pln">dataSource</span><span class="pun">());</span><span class="pln">
  factoryBean</span><span class="pun">.</span><span class="pln">setTransactionFactory</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ManagedTransactionFactory</span><span class="pun">());</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> factoryBean</span><span class="pun">.</span><span class="pln">getObject</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre></div>

    </div>
  
    <a name="programmatic"></a>
<div class="section" id="programmatic">
<h3><a name="a.E7.BC.96.E7.A8.8B.E5.BC.8F.E4.BA.8B.E5.8A.A1.E7.AE.A1.E7.90.86"></a>编程式事务管理</h3>
      
<p>
        MyBatis 的 <tt>SqlSession</tt> 提供几个方法来在代码中处理事务。但是当使用 MyBatis-Spring 时，你的 bean 将会注入由 Spring 管理的 <tt>SqlSession</tt> 或映射器。也就是说，Spring 总是为你处理了事务。
      </p>
      
<p>
        你不能在 Spring 管理的 <tt>SqlSession</tt> 上调用 <tt>SqlSession.commit()</tt>，<tt>SqlSession.rollback()</tt> 或 <tt>SqlSession.close()</tt> 方法。如果这样做了，就会抛出 <tt>UnsupportedOperationException</tt> 异常。在使用注入的映射器时，这些方法也不会暴露出来。
      </p>
      
<p>
        无论 JDBC 连接是否设置为自动提交，调用 <tt>SqlSession</tt> 数据方法或在 Spring 事务之外调用任何在映射器中方法，事务都将会自动被提交。
      </p>
      
<p>
        如果你想编程式地控制事务，请参考 <a class="externalLink" href="https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-programmatic">the Spring reference document(Data Access -Programmatic transaction management-)</a>。下面的代码展示了如何使用 <tt>PlatformTransactionManager</tt> 手工管理事务。
      </p>
      
<div class="source"><pre class="prettyprint"><span class="typ">TransactionStatus</span><span class="pln"> txStatus </span><span class="pun">=</span><span class="pln">
    transactionManager</span><span class="pun">.</span><span class="pln">getTransaction</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DefaultTransactionDefinition</span><span class="pun">());</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  userMapper</span><span class="pun">.</span><span class="pln">insertUser</span><span class="pun">(</span><span class="pln">user</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  transactionManager</span><span class="pun">.</span><span class="pln">rollback</span><span class="pun">(</span><span class="pln">txStatus</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">throw</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
transactionManager</span><span class="pun">.</span><span class="pln">commit</span><span class="pun">(</span><span class="pln">txStatus</span><span class="pun">);</span></pre></div>

      
<p>
        在使用 <tt>TransactionTemplate</tt> 的时候，可以省略对 <tt>commit</tt> 和 <tt>rollback</tt> 方法的调用。
      </p>

      
<div class="source"><pre class="prettyprint"><span class="typ">TransactionTemplate</span><span class="pln"> transactionTemplate </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TransactionTemplate</span><span class="pun">(</span><span class="pln">transactionManager</span><span class="pun">);</span><span class="pln">
transactionTemplate</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">txStatus </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  userMapper</span><span class="pun">.</span><span class="pln">insertUser</span><span class="pun">(</span><span class="pln">user</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre></div>

      
<p>
        注意：虽然这段代码使用的是一个映射器，但换成 SqlSession 也是可以工作的。
      </p>
      </div>
    </div>
  

        </div>
      </div>
    </div>
    <hr>
    <footer>
      <div class="container-fluid">
        <div class="row-fluid">
            <p>Copyright ©2010–2020
<a href="http://www.mybatis.org/">MyBatis.org</a>.
All rights reserved.</p>
        </div>
      </div>
    </footer>
  

<div class="xl-chrome-ext-bar" id="xl_chrome_ext_{4DB361DE-01F7-4376-B494-639E489D19ED}" style="display: none;">
      <div class="xl-chrome-ext-bar__logo"></div>

      <a id="xl_chrome_ext_download" href="javascript:;" class="xl-chrome-ext-bar__option">下载视频</a>
      <a id="xl_chrome_ext_close" href="javascript:;" class="xl-chrome-ext-bar__close"></a>
    </div></body></html>